package com.example.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component
public class LoggingAspect {

    // 定义一个切点：匹配 com.example.demo.service 包及其子包下所有类的所有方法
    @Pointcut("execution(* com.example.service..*.*(..))")
    public void serviceLayer() {}

//    // Before 通知：在匹配的方法执行前运行
//    @Before("serviceLayer()")
//    public void logBeforeMethod() {
//        log.info("【AOP Log】--- 方法即将执行 ---");
//    }
//
//    // After 通知：在匹配的方法执行后运行（无论是否成功）
//    @After("serviceLayer()")
//    public void logAfterMethod() {
//        log.info("【AOP Log】--- 方法执行完成 ---");
//    }
//
//    // AfterReturning 通知：在方法成功返回后运行
//    @AfterReturning(pointcut = "serviceLayer()", returning = "result")
//    public void logAfterReturning(Object result) {
//        log.info("【AOP Log】--- 方法成功返回，结果: {} ---", result);
//    }
//
//    // AfterThrowing 通知：在方法抛出异常后运行
//    @AfterThrowing(pointcut = "serviceLayer()", throwing = "e")
//    public void logAfterThrowing(Exception e) {
//        log.info("【AOP Log】--- 方法抛出异常: {} ---" , e.getMessage());
//    }

    //  Around 通知（功能最强大）：环绕方法执行
    @Around("serviceLayer()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();

        log.info("【AOP Around】--- 进入方法: {} ---, 参数: {} ---" , methodName , java.util.Arrays.toString(args));

        long startTime = System.currentTimeMillis();
        Object result;
        try {
            // 执行目标方法
            result = joinPoint.proceed();
        } catch (Throwable throwable) {
            log.info("【AOP Around】--- 方法: {} 执行异常: {} ---", methodName, throwable.getMessage());
            throw throwable; // 记得重新抛出异常
        } finally {
            long endTime = System.currentTimeMillis();
            log.info("【AOP Around】--- 退出方法: {} ---, 执行耗时: {}ms ---", methodName, (endTime - startTime));
        }
        log.info("【AOP Around】--- 方法: {} 执行结果: {} ---", methodName, result);
        return result;
    }
}